import React, { useRef } from "react";
import type { UploadFile, UploadProps } from "antd";
import { Upload } from "antd";
import { useQuery } from "@apollo/client";
import { GET_OSS_INFO } from "@/graphql/oss";
import ImgCrop from "antd-img-crop";

interface OSSDataType {
  dir: string;
  expire: string;
  host: string;
  accessId: string;
  policy: string;
  signature: string;
}

interface OSSUploadProps {
  label?: string;
  value?: UploadFile[];
  onChange?: (file?: UploadFile[]) => void;
}

const OSSUpload: React.FC<Readonly<OSSUploadProps>> = ({
  value,
  onChange,
  label,
}) => {
  const key = useRef("");
  const { data, refetch } = useQuery<{ getOSSInfo: OSSDataType }>(GET_OSS_INFO);
  const OSSData = data?.getOSSInfo;

  const handleChange: UploadProps["onChange"] = ({ file }) => {
    if (file.status === "removed") {
      onChange?.([]);
      return;
    }

    if (file.status === "done") {
      const newFile: UploadFile = {
        ...file,
        url: `${OSSData?.host}/${key.current}`,
      };
      onChange?.([newFile]);
    }
  };

  const getExtraData: UploadProps["data"] = (file) => {
    const suffix = file.name.slice(file.name.lastIndexOf("."));
    const fileName = Date.now() + suffix;
    key.current = `${OSSData?.dir}${fileName}`;
    return {
      key: key.current,
      OSSAccessKeyId: OSSData?.accessId,
      policy: OSSData?.policy,
      Signature: OSSData?.signature,
    };
  };

  const beforeUpload: UploadProps["beforeUpload"] = async (file) => {
    if (!OSSData) {
      return false;
    }

    const expire = Number(OSSData.expire) * 1000;
    if (expire < Date.now()) {
      await refetch();
    }
    return file;
  };

  return (
    <ImgCrop rotationSlider>
      <Upload
        name="file"
        fileList={value}
        action={OSSData?.host}
        listType="picture-card"
        onChange={handleChange}
        data={getExtraData}
        beforeUpload={beforeUpload}
        maxCount={1}
      >
        {(!value || value.length === 0) && label}
      </Upload>
    </ImgCrop>
  );
};

interface OSSImageUploadProps {
  label?: string;
  value?: UploadFile[];
  onChange?: (file?: UploadFile[]) => void;
}

const OSSImageUpload: React.FC<OSSImageUploadProps> = ({
  label = "上传图片",
  onChange = () => {},
  value = [],
}) => <OSSUpload label={label} value={value} onChange={onChange} />;

export default OSSImageUpload;
